package srzy.dao

import java.sql.DriverManager
import srzy.common.Logging
import srzy.common.Config
import scala.collection.mutable.ListBuffer
import srzy.data.DBCompInfo
import srzy.common.Common
import srzy.data.ShellCompInfo

abstract class DBUtil extends srzy.common.Logging {

  val url: String

  def executeUpdate(sqlList: List[String]) = {
    logger.debug("execute sql list start")
    val conn = DriverManager.getConnection(url)
    try {
      val statement = conn.createStatement
      sqlList.map((sql: String) => {
        logger.debug("sql:" + sql)
        statement.executeUpdate(sql)
      })
      conn.commit
    } finally {
      conn.close
    }
    logger.debug("executeSQL over")
  }

  def executeUpdate(sql: String) = {
    logger.debug("execute sql start")
    val conn = DriverManager.getConnection(url)
    try {
      val statement = conn.createStatement
      logger.debug("sql:" + sql)
      statement.executeUpdate(sql)
      conn.commit
    } finally {
      conn.close
    }
    logger.debug("executeSQL over")
  }

  def executeLine(sql: String): String = {
    logger.debug("executeLine start")
    val conn = DriverManager.getConnection(url)
    try {
      val statement = conn.createStatement
      logger.debug("sql:" + sql)
      val rs = statement.executeQuery(sql)
      if (!rs.next()) {
        return ""
      }
      return rs.getString(1)
      //      res = rs.getString(1)
      //      return res
    } finally {
      conn.close
    }
  }

  def getDBCompInfo(): Map[String, List[DBCompInfo]] = {
    logger.debug("getDBCompInfo start")
    val sql = """SELECT A.CASE_ID       AS CASE_NAME,
       A.ORDER_ID,
       B.CHECK_CONTENT AS SQL,
       A.CHECK_PARA    AS PARA,
       A.PRE_RESULT
  FROM OCS_AUTO_CASE_CHECK_PARA A
  LEFT JOIN OCS_AUTO_CHECK_CONFIG B
    ON (A.CHECK_ID = B.CHECK_ID)
 WHERE B.CHECK_TYPE = 2
 ORDER BY A.CASE_ID, A.ORDER_ID"""
    logger.debug("sql:" + sql)

    val conn = DriverManager.getConnection(url)
    try {
      val statement = conn.createStatement
      val rs = statement.executeQuery(sql)

      var m = scala.collection.mutable.Map[String, collection.mutable.ListBuffer[DBCompInfo]]()
      while (rs.next()) {
        val caseName = Common.ifnull(rs.getString(1))
        if (!m.contains(caseName))
          m.put(caseName, new collection.mutable.ListBuffer[DBCompInfo])
        m.apply(caseName) += (new DBCompInfo {
          oraderId = Common.ifnull(rs.getString(2))
          originalSQL = Common.ifnull(rs.getString(3))
          para = Common.ifnull(rs.getString(4))
          preResult = Common.ifnull(rs.getString(5))
        })
      }
      m.toList.map(x => (x._1, x._2.toList)).toMap
    } finally {
      conn.close
      logger.debug("getDBCompInfo over")
    }
  }

  def getShellCompInfo(): Map[String, List[ShellCompInfo]] = {
    logger.debug("getShellCompInfo start")
    val sql = """SELECT A.CASE_ID       AS CASE_NAME,
       A.ORDER_ID,
       B.CHECK_CONTENT AS SHELL,
       A.PRE_RESULT
  FROM OCS_AUTO_CASE_CHECK_PARA A
  LEFT JOIN OCS_AUTO_CHECK_CONFIG B
    ON (A.CHECK_ID = B.CHECK_ID)
 WHERE B.CHECK_TYPE = 3
 ORDER BY A.CASE_ID, A.ORDER_ID"""
    logger.debug("sql:" + sql)
    val conn = DriverManager.getConnection(url)
    try {
      val statement = conn.createStatement
      val rs = statement.executeQuery(sql)

      var m = scala.collection.mutable.Map[String, collection.mutable.ListBuffer[ShellCompInfo]]()
      while (rs.next()) {
        val caseName = Common.ifnull(rs.getString(1))
        if (!m.contains(caseName))
          m.put(caseName, new collection.mutable.ListBuffer[ShellCompInfo])
        m.apply(caseName) += (new ShellCompInfo {
          oraderId = Common.ifnull(rs.getString(2))
          shell = Common.ifnull(rs.getString(3))
          preResult = Common.ifnull(rs.getString(4))
        })
      }
      m.toList.map(x => (x._1, x._2.toList)).toMap
    } finally {
      conn.close
      logger.debug("getShellCompInfo over")
    }
  }

  def getCaseInfo(): List[(String, String)] = {
    logger.debug("get CaseInfo start")
    val sql = """SELECT CASE_PWD, EXCEPT_CONDITION FROM OCS_AUTO_CASE_ONLINE WHERE DEAL_FLAG = 0 ORDER BY CASE_ID"""
    logger.debug("sql:" + sql)
    val conn = DriverManager.getConnection(url)
    try {
      val statement = conn.createStatement
      val rs = statement.executeQuery(sql)
      var lb = ListBuffer.empty[(String, String)]
      while (rs.next()) {
        lb.append((Common.ifnull(rs.getString(1)), Common.ifnull(rs.getString(2))))
      }
      lb.toList
    } finally {
      conn.close
      logger.debug("get CaseInfo over")
    }
  }

}

object DBUtil extends srzy.common.Logging {

  val dbTypes = ListBuffer.empty[String]
  val driverMap = Map("oracle" -> "oracle.jdbc.driver.OracleDriver",
    "Altibase" -> "Altibase.jdbc.driver.AltibaseDriver",
    "timesten" -> "com.timesten.jdbc.TimesTenDriver")

  val dbUtilMap: scala.collection.mutable.Map[String, DBUtil] = scala.collection.mutable.Map.empty[String, DBUtil]

  def apply(source: String) = {
    if (source == "InMemorySource" && Config.fileType == "XML") {
      applyURL(Config.getValue("root", "config", "RBSource", "URL"))
    } else {
      applyURL(Config.getValue("root", "config", source, "URL"))
    }
  }

  def applyURL(url: String) = {
    val r1 = """(?<=jdbc:)[a-zA-Z]*""".r
    val URL = url
    val dbType = r1.findFirstIn(URL) match {
      case Some(v) => v
      case None => throw new Exception("database url can not identify")
    }
    val driver = driverMap.get(dbType) match {
      case Some(v) => v
      case None => throw new Exception("unknown database type")
    }

    logger.debug("URL:" + URL)
    logger.debug("Driver:" + driver)

    if (!dbTypes.contains(driver)) {
      dbTypes.append(dbType)
      Class.forName(driver)
      logger.debug("create driver " + driver)
    }

    if (dbUtilMap.contains(URL)) {
      dbUtilMap.apply(URL)
    } else {
      val n = new DBUtil {
        val url = URL
      }
      logger.debug("url:" + n.url)
      dbUtilMap.update(URL, n)
      n
    }
  }

  //  def init(source: String) = {
  //    val r1 = """(?<=jdbc:)[a-zA-Z]*""".r
  //
  //    val url = if (source == "InMemorySource" && Config.fileType == "XML") {
  //      Config.getValue("root", "config", "RBSource", "URL")
  //    } else {
  //      Config.getValue("root", "config", source, "URL")
  //    }
  //
  //    val dbType = r1.findFirstIn(url) match {
  //      case Some(v) => v
  //      case None => throw new Exception("database url can not identify")
  //    }
  //
  //    val driver = driverMap.get(dbType) match {
  //      case Some(v) => v
  //      case None => throw new Exception("unknown database type")
  //    }
  //
  //    logger.debug("Source:" + source)
  //    logger.debug("URL:" + url)
  //    logger.debug("Driver:" + driver)
  //
  //    if (!dbType.contains()) {
  //      dbTypes.append(dbType)
  //      Class.forName(driver)
  //    }
  //    url
  //  }

}